package com.lsh.payment.core.handler.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lsh.payment.api.model.basevo.BaseResponse;
import com.lsh.payment.api.model.basevo.ExceptionStatus;
import com.lsh.payment.api.model.refund.RefundResponse;
import com.lsh.payment.core.handler.AbstractRefundChannelHandler;
import com.lsh.payment.core.model.payenum.RefundStatus;
import com.lsh.payment.core.model.payenum.WxRefundStatus;
import com.lsh.payment.core.model.payment.PayDeal;
import com.lsh.payment.core.model.refund.PayRefund;
import com.lsh.payment.core.service.wxpay.IWxRefundService;
import com.lsh.payment.core.strategy.vo.wxpay.WxPayRefundQueryResult;
import com.lsh.payment.core.strategy.vo.wxpay.WxPayRefundResult;
import com.lsh.payment.core.util.BigDecimalUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * Project Name: lsh-payment
 *
 * @author peter
 * @date 17/7/6
 * 北京链商电子商务有限公司
 * Package
 * desc:
 */
@Service
public class WxRefundHandler extends AbstractRefundChannelHandler {

    private static Logger logger = LoggerFactory.getLogger(WxRefundHandler.class);

    @Autowired
    private IWxRefundService wxRefundService;

    @Override
    public RefundResponse refund(PayRefund payRefund, PayDeal payDeal) {

        RefundResponse refundResponse = new RefundResponse();
        //申请退款
        Map<String, String> wxRefundRequestBody = this.getRefundRequestBody(payDeal);
        //微信支付流水号
        wxRefundRequestBody.put("transaction_id", payDeal.getChannelTransaction());
        //支付平台退款流水号
        wxRefundRequestBody.put("out_refund_no", payRefund.getPaymentRefundNo());
        wxRefundRequestBody.put("total_fee", BigDecimalUtils.yuanToFen(payDeal.getReceiveAmount()).toString());
        wxRefundRequestBody.put("refund_fee", BigDecimalUtils.yuanToFen(payRefund.getRefundAmount()).toString());

        WxPayRefundResult wxPayRefundResult = wxRefundService.refund(wxRefundRequestBody);

        if (!wxPayRefundResult.getReturnCode().equals("SUCCESS")) {
            logger.info(payRefund.getPaymentRefundNo() + "【申请退款失败】微信返回信息 {}", JSON.toJSONString(wxPayRefundResult));
            refundResponse.errorRefundResponse(wxPayRefundResult.getReturnCode(), wxPayRefundResult.getReturnMsg());
        }

        if (wxPayRefundResult.getResultCode().equals("SUCCESS")) {

            payRefund.setChannelRefundId(wxPayRefundResult.getRefundId());
            if (this.getRefundOrderStatusService(RefundStatus.REFUND_ING).modifyStatus(payRefund,true)) {
                JSONObject content = new JSONObject();
                content.put("payment_refund_no",payRefund.getPaymentRefundNo());
                refundResponse.setContent(content);
            }

            refundResponse.setRet(Integer.parseInt(ExceptionStatus.SUCCESS.getCode()));
            refundResponse.setMsg(ExceptionStatus.SUCCESS.getMessage());
        } else {

            payRefund.setChannelRefundId(wxPayRefundResult.getRefundId());
            String ext = payRefund.getExt();
            JSONObject extJson;
            if (StringUtils.isNotBlank(ext)) {
                extJson = JSON.parseObject(ext);
            } else {
                extJson = new JSONObject();
            }
            extJson.put("err_code", wxPayRefundResult.getErrCode());
            extJson.put("err_code_des", wxPayRefundResult.getErrCodeDes());

            payRefund.setExt(extJson.toJSONString());
            if (this.getRefundOrderStatusService(RefundStatus.REFUND_EXCEPTION).modifyStatus(payRefund,false)) {

                JSONObject content = new JSONObject();
                content.put("payment_refund_no",payRefund.getPaymentRefundNo());
                refundResponse.setContent(content);
            }

            logger.info("wxPayRefundResult info is " + JSON.toJSONString(wxPayRefundResult));
            refundResponse.setRet(2001005);
            refundResponse.setMsg("退款申请失败," + wxPayRefundResult.getErrCode() + "," + wxPayRefundResult.getErrCodeDes());
        }

        return refundResponse;
    }


    private Map<String, String> getRefundRequestBody(PayDeal payDeal){
        Map<String, String> refundRequestBody = new HashMap<>(10);
        if(payDeal.getPayWay().equals("h5")){
            refundRequestBody.put("refund_way", "h5");
        }else{
            refundRequestBody.put("refund_way", "app");
        }

        return refundRequestBody;
    }

    @Override
    public BaseResponse refundQuery(PayRefund payRefund, PayDeal payDeal) {

        BaseResponse baseResponse = new BaseResponse();

        if (payRefund.getRefundStatus() == RefundStatus.REFUND_ING.getValue()) {
            Map<String, String> wxRefundQueryRequestBody = this.getRefundRequestBody(payDeal);
            //微信退款流水号
            wxRefundQueryRequestBody.put("refundId", payRefund.getChannelRefundId());
            //支付平台退款流水号
            wxRefundQueryRequestBody.put("paymentRefundNo", payRefund.getPaymentRefundNo());

            logger.info("【微信退款查询】{}", JSON.toJSONString(wxRefundQueryRequestBody));
            WxPayRefundQueryResult wxPayRefundQueryResult = wxRefundService.refundQuery(wxRefundQueryRequestBody);


            if (!wxPayRefundQueryResult.getReturnCode().equals("SUCCESS")) {
                baseResponse.setRet(2005001);
                baseResponse.setMsg("查询退款失败");

                return baseResponse;
            }

            if (wxPayRefundQueryResult.getResultCode().equals("SUCCESS")) {
                for (WxPayRefundQueryResult.RefundRecord refundRecord : wxPayRefundQueryResult.getRefundRecords()) {
                    logger.info("退款进度信息是 {}", JSON.toJSONString(refundRecord));
                    if (refundRecord.getOutRefundNo().equals(payRefund.getPaymentRefundNo())) {


                        if (refundRecord.getRefundStatus().equals(WxRefundStatus.WX_REFUND_SUCCESS.getName())) {
                            payRefund.setRefundRecvAccout(refundRecord.getRefundRecvAccout());

                            if (this.getRefundOrderStatusService(RefundStatus.REFUND_SUCCESS).modifyStatus(payRefund,true)) {
                                baseResponse.setRet(Integer.valueOf(ExceptionStatus.SUCCESS.getCode()));
                                baseResponse.setMsg("退款成功");
                            } else {
                                baseResponse.setRet(Integer.valueOf(ExceptionStatus.E2000000.getCode()));
                                baseResponse.setMsg("退款进行中");
                            }
                        } else if (refundRecord.getRefundStatus().equals(WxRefundStatus.WX_REFUND_CLOSE.getName())) {

                            payRefund.setRefundRecvAccout(refundRecord.getRefundRecvAccout());
                            if (this.getRefundOrderStatusService(RefundStatus.REFUND_CLOSE).modifyStatus(payRefund,true)) {
                                baseResponse.setRet(Integer.valueOf(ExceptionStatus.E2006001.getCode()));
                                baseResponse.setMsg(ExceptionStatus.E2006001.getMessage());
                            } else {
                                baseResponse.setRet(Integer.valueOf(ExceptionStatus.E2000000.getCode()));
                                baseResponse.setMsg("退款进行中");
                            }
                        } else if (refundRecord.getRefundStatus().equals(WxRefundStatus.WX_REFUND_ING.getName())) {
                            baseResponse.setRet(Integer.valueOf(ExceptionStatus.E2000000.getCode()));
                            baseResponse.setMsg("退款进行中");
                        } else if (refundRecord.getRefundStatus().equals(WxRefundStatus.WX_REFUND_CHANGE.getName())) {
                            //CHANGE—转入代发，退款到银行发现用户的卡作废或者冻结了，导致原路退款银行卡失败，资金回流到商户的现金帐号，需要商户人工干预，通过线下或者财付通转账的方式进行退款。
                            // TODO 发邮件
                            if (this.getRefundOrderStatusService(RefundStatus.REFUND_EXCEPTION).modifyStatus(payRefund,true)) {
                                baseResponse.setRet(Integer.valueOf(ExceptionStatus.E2006002.getCode()));
                                baseResponse.setMsg("退款代发...");
                            } else {
                                baseResponse.setRet(Integer.valueOf(ExceptionStatus.E2000000.getCode()));
                                baseResponse.setMsg("退款进行中");
                            }
                        }
                    }
                }

            } else {

                baseResponse.setRet(Integer.valueOf(ExceptionStatus.E2006003.getCode()));
                baseResponse.setMsg("退款申请成功，查询退款结果FAIL,请联系 技术人员");
            }
        } else if (payRefund.getRefundStatus() == RefundStatus.REFUND_SUCCESS.getValue()) {
            baseResponse.setRet(0);
            baseResponse.setMsg("微信退款成功");
        } else if (payRefund.getRefundStatus() == RefundStatus.REFUND_NEW.getValue()) {
            baseResponse.setRet(Integer.valueOf(ExceptionStatus.E2000000.getCode()));
            baseResponse.setMsg("微信退款进行中");
        } else if (payRefund.getRefundStatus() == RefundStatus.REFUND_APPLY.getValue()) {
            baseResponse.setRet(Integer.valueOf(ExceptionStatus.E2000000.getCode()));
            baseResponse.setMsg("微信退款进行中");
        } else if (payRefund.getRefundStatus() == RefundStatus.REFUND_CLOSE.getValue()) {
            baseResponse.setRet(Integer.valueOf(ExceptionStatus.E2006001.getCode()));
            baseResponse.setMsg(ExceptionStatus.E2006001.getMessage());
        } else {
            baseResponse.setRet(Integer.valueOf(ExceptionStatus.E2006002.getCode()));
            baseResponse.setMsg("微信退款失败");
        }

        return baseResponse;
    }


}
